package com.egao.platform.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.egao.platform.system.mapper.AuthoritiesMapper;
import com.egao.platform.system.entity.Authorities;
import com.egao.platform.system.service.AuthoritiesService;
import io.swagger.models.HttpMethod;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import springfox.documentation.service.Documentation;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;

import java.util.*;

/**
 * 权限服务实现类
 * Created by wangfan on 2018-12-24 16:10
 */
@Service
public class AuthoritiesServiceImpl extends ServiceImpl<AuthoritiesMapper, Authorities> implements AuthoritiesService {
    @Autowired
    private DocumentationCache documentationCache;
    @Autowired
    private ServiceModelToSwagger2Mapper mapper;

    @Override
    public List<String> listByRoleId(Integer roleId) {
        List<Integer> roleIds = new ArrayList<>();
        if (roleId != null) {
            roleIds.add(roleId);
        }
        return listByRoleIds(roleIds);
    }

    @Override
    public List<String> listByRoleIds(List<Integer> roleIds) {
        if (roleIds == null || roleIds.size() == 0) {
            return new ArrayList<>();
        }
        return baseMapper.listByRoleIds(roleIds);
    }

    @Override
    public List<String> listByUserId(Integer userId) {
        return baseMapper.listByUserId(userId);
    }

    @Override
    public List<Authorities> selectRoleChecked(List<Authorities> authorities, Integer roleId) {
        if (roleId != null) {
            List<String> roleAuth = listByRoleId(roleId);
            for (Authorities one : authorities) {
                one.setChecked(0);
                for (String authority : roleAuth) {
                    if (one.getAuthority().equals(authority)) {
                        one.setChecked(1);
                        break;
                    }
                }
            }
        }
        return authorities;
    }

    @Override
    public List<Authorities> scan() {
        List<Authorities> authList = new ArrayList<>();
        Documentation documentation = documentationCache.documentationByGroup("default");
        if (documentation != null) {
            Swagger swagger = mapper.mapDocumentation(documentation);
            Map<String, Path> paths = swagger.getPaths();
            Set<String> pathKeys = paths.keySet();
            for (String pathKey : pathKeys) {
                Path path = paths.get(pathKey);
                Map<HttpMethod, Operation> operationMap = path.getOperationMap();
                Set<HttpMethod> httpMethods = operationMap.keySet();
                for (HttpMethod httpMethod : httpMethods) {
                    Operation operation = operationMap.get(httpMethod);
                    List<String> tags = operation.getTags();
                    // 封装成权限对象
                    Authorities auth = new Authorities();
                    auth.setAuthority(httpMethod.toString().toLowerCase() + ":" + pathKey);
                    auth.setAuthorityName(operation.getSummary());
                    auth.setParentName(tags != null && tags.size() > 0 ? tags.get(0) : "");
                    authList.add(auth);
                }
            }
        }
        // 排序，按照模块名、类名、请求方式排序
        authList.sort(new Comparator<Authorities>() {
            @Override
            public int compare(Authorities o1, Authorities o2) {
                String m1 = getModelName(o1.getAuthority()), m2 = getModelName(o2.getAuthority());
                if (m1.equals(m2)) {
                    if (o1.getParentName().equals(o2.getParentName())) {
                        Integer r1 = getReqMethod(o1.getAuthority()), r2 = getReqMethod(o2.getAuthority());
                        if (r1.equals(r2)) {
                            return o1.getAuthority().compareTo(o2.getAuthority());
                        }
                        return r1.compareTo(r2);
                    }
                    return o1.getParentName().compareTo(o2.getParentName());
                }
                return m1.compareTo(m2);
            }
        });
        // 设置排序号
        for (int i = 0; i < authList.size(); i++) {
            authList.get(i).setSortNumber(i);
        }
        return authList;
    }

    /**
     * 从权限标识中截取出模块名
     */
    private String getModelName(String authority) {
        int start = authority.indexOf(":/api/");
        if (start != -1) {
            int end = authority.indexOf("/", start);
            return end == -1 ? "" : authority.substring(start, end);
        }
        return "";
    }

    /**
     * 请求方式按照get、post、put、delete排序
     */
    private Integer getReqMethod(String authority) {
        if (authority.indexOf("get:") == 0) {
            return 0;
        } else if (authority.indexOf("post:") == 0) {
            return 1;
        } else if (authority.indexOf("put:") == 0) {
            return 2;
        } else if (authority.indexOf("delete:") == 0) {
            return 3;
        }
        return 4;
    }

}
